<?php
/**
 *	[TWCMS] (C)2012 TongWang Inc.
 *	$Id: upload.class.php 2 2013-04-27 07:14:17Z nanown@qq.com $
 */
defined('IN_TWCMS') || exit('Access Denied');

class upload{
	private $fileField;
	private $file;
	private $config;
	private $upRoot;	//文件根目录
	private $fileName;	//原文件名
	private $fileSize;	//文件大小
	private $fileType;	//文件类型
	private $fileExt;	//原扩展名
	private $filePath;	//文件路径
	private $isImage;	//是否图片
    private $stateInfo;
	private $stateMap = array(
		'0' => 'SUCCESS',
		'1' => '文件大小超出 upload_max_filesize 限制',
		'2' => '文件大小超出 MAX_FILE_SIZE 限制',
		'3' => '文件未被完整上传',
		'4' => '没有文件被上传',
		'5' => '上传文件为空',
		'6' => '缺少临时文件夹',
		'7' => '写文件失败',
		'8' => '上传被其它扩展中断',
		'POST' => '未接收到 $_POST 数据',
		'FILES' => '未接收到 $_FILES 数据',
		'SIZE' => '文件大小超出网站限制',
		'EXT' => '不允许的扩展名',
		'DIR' => '目录创建失败',
		'IO' => '输入输出错误',
		'UNKNOWN' => '未知错误',
		'MOVE' => '文件保存时出错'
	);

	#提示: $config 只有三个参数 int maxSize | string allowExt | string tmpDir
	public function __construct($fileField, $config, $base64=false) {
		$this->upRoot = TWCMS_ROOT.TWCMS_UPLOAD;
		$this->fileField = $fileField;
		$this->config = $config;
		$this->stateInfo = $this->stateMap[0];
		$this->upFile($base64);
	}

	#上传文件
	private function upFile($base64) {
		if('base64' == $base64) {
			if(empty($_POST[$this->fileField])) {
				$this->stateInfo = $this->getStateInfo('POST');
				return;
			}
			$content = $_POST[$this->fileField];
			$this->base64ToImage($content);
			return;
		}

		if(empty($_FILES[$this->fileField])) {
			$this->stateInfo = $this->getStateInfo('FILES');
			return;
		}
		$this->file = $_FILES[$this->fileField];
		if($this->file['error']) {
			$this->stateInfo = $this->getStateInfo($this->file['error']);
			return;
		}
		if(!is_uploaded_file($this->file['tmp_name'])) {
			$this->stateInfo = $this->getStateInfo('UNKNOWN');
			return;
		}

		$this->fileName = $this->file['name'];
		$this->fileSize = $this->file['size'];
		$this->fileType = $this->file['type'];
		$this->fileExt = $this->getFileExt();
		if(!$this->checkSize()) {
			$this->stateInfo = $this->getStateInfo('SIZE');
			return;
		}
		if(!$this->checkExt()) {
			$this->stateInfo = $this->getStateInfo('EXT');
			return;
		}
		$dir = empty($this->config['tmpDir']) ? date('Ym/d') : $this->config['tmpDir'];
		if(!$this->_mkdir($this->upRoot.$dir)) {
			$this->stateInfo = $this->getStateInfo('DIR');
			return;
		}

		$this->filePath = $dir.'/'.$this->getName();
		if($this->stateInfo == $this->stateMap[0]) {
			if(!move_uploaded_file($this->file['tmp_name'] , $this->upRoot.$this->filePath)) {
				$this->stateInfo = $this->getStateInfo('MOVE');
			}
		}
	}

	#处理base64编码的图片上传
	private function base64ToImage($base64Data) {
		$img = base64_decode($base64Data);

		$dir = date('Ym/d');
		if(!$this->_mkdir($this->upRoot.$dir)) {
			$this->stateInfo = $this->getStateInfo('DIR');
			return;
		}
		$this->fileName = '';
		$this->fileSize = strlen($img);
		$this->fileType = 'image/png';
		$this->fileExt = 'png';
		$this->filePath = $dir.'/'.$this->getName();
		if(!file_put_contents($this->upRoot.$this->filePath, $img)) {
			$this->stateInfo = $this->getStateInfo('IO');
			return;
		}
	}

	#检测文件大小
	private function checkSize() {
		return $this->fileSize <= ($this->config['maxSize']*1024);
	}

	#检测文件类型检测
	private function checkExt() {
		return in_array($this->fileExt, $this->getAllowExt());
	}

	#获取是否是图片文件
	private function getIsImage() {
		return in_array($this->fileExt, array('gif', 'jpg', 'jpeg', 'png', 'bmp')) ? 1 : 0;
	}

	#获取当前上传成功文件的各项信息
	public function getFileInfo() {
		return array(
			'state' => $this->stateInfo,
			'name' => $this->fileName,
			'size' => $this->fileSize,
			'type' => $this->fileType,
			'ext' => $this->fileExt,
			'url' => $this->filePath,
			'isimage' => $this->getIsImage()
		);
	}

	#上传错误检查
	private function getStateInfo($errCode) {
		return empty($this->stateMap[$errCode]) ? $this->stateMap['UNKNOWN'] : $this->stateMap[$errCode];
	}

	#重命名文件
	private function getName() {
		$Exts = array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'swf', 'flv', 'mp3', 'mp4', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb', 'wps', 'doc', 'docx', 'xsl', 'xls', 'xlsx', 'ppt', 'htm', 'html', 'txt', 'zip', 'rar', 'gz', 'bz2', 'iso', 'chm');
		$fileSuffix = in_array($this->fileExt, $Exts) ? '.'.$this->fileExt : '_'.$this->fileExt.'.file';
		return date('His').random(16, 3).$fileSuffix;
	}

	#获取允许上传的扩展名
	private function getAllowExt() {
		$Arr = explode(',', $this->config['allowExt']);
		$ret = array();
		foreach($Arr as $val) {
			$val = trim($val);
			if($val) $ret[] = $val;
		}
		return $ret;
	}

	#获取文件扩展名
	private function getFileExt() {
		return preg_replace('/\W/', '', strtolower(substr(strrchr($this->file['name'], '.'), 1, 10)));
	}

	#递归创建目录
	private function _mkdir($dir, $mode = 0777){
		$ret = true;
		if(!is_dir($dir)) {
			_mkdir(dirname($dir), $mode) || $ret = false;
			mkdir($dir, $mode) || $ret = false;
			touch($dir.D.'index.htm'); chmod($dir.D.'index.htm', 0777);
		}
		return $ret;
	}
}